{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "823a4976-8803-4914-80a3-74388ab555ea",
   "metadata": {},
   "source": [
    "## 路径参数校验"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f71b6e28-9b0c-439c-a35a-31e0ce0af646",
   "metadata": {},
   "source": [
    "可以使用 Path 为路径参数声明类型的校验和元数据。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d970f754-a31b-46a6-b0ca-11356bc3c265",
   "metadata": {},
   "source": [
    "## 导入 Path"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8aba008-cc12-4fba-abd6-abc3c5473231",
   "metadata": {},
   "source": [
    "首先，从 fastapi 导入 Path：\n",
    "\n",
    "声明元数据，尽可能选择使用 Annotated 语法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e5a97dcd-6704-41d4-883a-6fd6d7c00def",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [18944]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:49766 - \"GET /items/5 HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [18944]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from typing import Annotated\n",
    "from fastapi import FastAPI, Path\n",
    "app = FastAPI()\n",
    "@app.get(\"/items/{item_id}\")\n",
    "async def read_items(\n",
    "    item_id: Annotated[int, Path(title=\"The ID of the item to get\")]\n",
    "):\n",
    "    results = {\"item_id\": item_id}\n",
    "    return results\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6ccbad1-dbca-4eaf-a8eb-40b766b4d264",
   "metadata": {},
   "source": [
    "浏览器中输入 http://127.0.0.1:8009/items/5\n",
    "\n",
    "会看到 {\"item_id\":5}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39121baf-a9e3-4ea8-84ba-f58f81820516",
   "metadata": {},
   "source": [
    "## 数值校验"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "487445c3-dca4-4c64-839e-e62468851ee5",
   "metadata": {},
   "source": [
    "添加 ge=5 后，item_id 将必须是一个大于（greater than）或等于（equal）5 的整数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6ba7df53-44a6-4652-a5e5-60a171898088",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [18944]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:56540 - \"GET /items/4 HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:56539 - \"GET /items/6 HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:56544 - \"GET /items/4 HTTP/1.1\" 422 Unprocessable Entity\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [18944]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from typing import Annotated\n",
    "from fastapi import FastAPI, Path\n",
    "app = FastAPI()\n",
    "@app.get(\"/items/{item_id}\")\n",
    "async def read_items(\n",
    "    item_id: Annotated[int, Path(title=\"The ID of the item to get\", ge=5)]\n",
    "):\n",
    "    results = {\"item_id\": item_id}\n",
    "    return results\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5add874-f2f4-4d6a-9778-082e34b0080b",
   "metadata": {},
   "source": [
    "浏览器中输入 http://127.0.0.1:8009/items/6\n",
    "\n",
    "会看到 {\"item_id\":6}\n",
    "\n",
    "如果输入 http://127.0.0.1:8009/items/4\n",
    "会看到 {\"detail\":[{\"type\":\"greater_than_equal\",\"loc\":[\"path\",\"item_id\"],\"msg\":\"Input should be greater than or equal to 5\",\"input\":\"4\",\"ctx\":{\"ge\":5},\"url\":\"https://errors.pydantic.dev/2.5/v/greater_than_equal\"}]}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1d58d9fb-469e-45e5-a3dd-7f105244f94d",
   "metadata": {},
   "source": [
    "数值校验同样适用于 float 值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "72d1e1e1-ebae-4f9c-a7e2-0557d8b822c8",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [18944]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:56566 - \"GET /items/5.6 HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:56566 - \"GET /items/5.4 HTTP/1.1\" 422 Unprocessable Entity\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [18944]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from typing import Annotated\n",
    "from fastapi import FastAPI, Path\n",
    "app = FastAPI()\n",
    "@app.get(\"/items/{item_id}\")\n",
    "async def read_items(\n",
    "    item_id: Annotated[float, Path(title=\"The ID of the item to get\", ge=5.5)]\n",
    "):\n",
    "    results = {\"item_id\": item_id}\n",
    "    return results\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30beabb6-72e3-4a78-b0fe-4f7a400f60ba",
   "metadata": {},
   "source": [
    "浏览器中输入 http://127.0.0.1:8009/items/5.6\n",
    "\n",
    "会看到 {\"item_id\":5.6}\n",
    "\n",
    "如果输入 http://127.0.0.1:8009/items/5.4\n",
    "会看到 {\"detail\":[{\"type\":\"greater_than_equal\",\"loc\":[\"path\",\"item_id\"],\"msg\":\"Input should be greater than or equal to 5.5\",\"input\":\"5.4\",\"ctx\":{\"ge\":5.5},\"url\":\"https://errors.pydantic.dev/2.5/v/greater_than_equal\"}]}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84946564-2468-4672-bf0b-62c9972ab3c9",
   "metadata": {},
   "source": [
    "可选的声明数值校验：\r\n",
    "\r\n",
    "gt：大于（greater tha\n",
    "n）\r\n",
    "ge：大于等于（greater than or equ\n",
    "al）\r\n",
    "lt：小于（less t\n",
    "han）\r\n",
    "le：小于等于（less than or equal）"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
